//
// Created by pzw on 24-3-1.
//

#ifndef QTTEST_TREEMAP_H
#define QTTEST_TREEMAP_H

#include <map>
#include <set>
#include <iostream>

/**
 * C++版本的TreeMap，与java的TreeMap的函数一模一样
 *
 * @tparam K       - key
 * @tparam V       - value
 * @tparam Compare - 比较器
 */
template<typename K, typename V, typename Compare = std::less<K>>
class TreeMap {
private:
    /**
     * C++并没有明确禁止使用引用类型作为类的成员变量，但是通常不建议在类中直接使用引用类型作为成员变量的原因有几点：
     *
     * 1. **初始化问题**：引用类型必须在构造函数的初始化列表中进行初始化，而不能在构造函数内部再次赋值。
     * 这会导致在类的构造函数中必须保证引用类型成员变量被正确初始化，可能会增加复杂性。
     *
     * 2. **所有权问题**：引用类型成员变量并不拥有对象所有权，它只是一个别名。
     * 这意味着在类的生命周期内，引用可能会指向一个已经销毁的对象，导致悬空引用的问题。
     *
     * 3. **赋值问题**：引用类型一旦初始化后，无法重新绑定到其他对象，
     * 这会限制了类的灵活性，因为无法在类内部改变引用所指向的对象。
     *
     * 4. **内存管理问题**：引用类型成员变量并不负责对象的内存管理，
     *    **如果引用指向的对象在类的生命周期内被销毁，会导致悬空引用或者访问非法内存的问题。
     *
     * **基于上述原因**：通常建议避免直接在类中使用引用类型作为成员变量。
     * 如果需要引用语义，可以考虑使用指针类型，并在类的构造函数和析构函数中负责管理内存，
     * 以确保对象的生命周期和所有权得到正确管理。
     *
     * **综上**：成员变量：要么std::map<K, V, Compare> *map; 要么std::map<K, V, Compare> map;
     * **最好不要使用**：std::map<K, V, Compare> &map;的形式。
     */
    std::map<K, V, Compare> *map;

public:
    TreeMap() = default;

    explicit TreeMap(const Compare &comp) : map(new std::map<K, V, Compare>(comp)) {}

    explicit TreeMap(std::map<K, V, Compare> *m) : map(m) {}

    ~TreeMap() {
        delete map;
    };

public:
    void clear();
    TreeMap<K, V, Compare> clone() const;
    Compare comparator() const;
    bool containsKey(const K &key) const;
    bool containsValue(const V &value) const;
    std::set<std::pair<K, V>> entrySet();
    std::pair<K, V> firstEntry();
    K firstKey();
    std::pair<K, V> floorEntry(const K &key);
    K floorKey(const K &key);
    V get(const K &key);
    V operator[](const K &key);
    std::map<K, V> headMap(const K &toKey);
    std::map<K, V> higherEntry(const K &key);
    K higherKey(const K &key);
    std::set<K> keySet();
    std::pair<K, V> lastEntry();
    K lastKey();
    std::pair<K, V> lowerEntry(const K &key);
    K lowerKey(const K &key);
    std::set<K> navigableKeySet();
    std::pair<K, V> pollFirstEntry();
    std::pair<K, V> pollLastEntry();
    V put(const K &key, const V &value);
    void putAll(const std::map<K, V> &m);
    V remove(const K &key);
    int size();
    std::map<K, V> subMap(const K &fromKey, bool fromInclusive, const K &toKey, bool toInclusive);
    std::map<K, V> tailMap(const K &fromKey);
    std::map<K, V> headMap(const K &toKey, bool inclusive);
    std::set<V> values();
};

int TreeMap_main();

#endif //QTTEST_TREEMAP_H
